package top.bulk.retry.listener;

import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.RetryListener;
import org.springframework.stereotype.Component;

/**
 * 监听器,每一次重试都会被监听到，可以做一些统一处理，类似 aop
 *
 * @author 散装java
 * @date 2024-07-03
 */
@Component
@Slf4j
public class BulkRetryListener implements RetryListener {
    /**
     * 用作测试上下文传递参数的key
     */
    private static final String KEY = "bulk-java";

    /**
     * 方法在重试开始前调用，用于设置重试所需的状态或资源。通过返回false可以终止重试，抛出TerminatedRetryException异常
     */
    @Override
    public <T, E extends Throwable> boolean open(RetryContext retryContext, RetryCallback<T, E> retryCallback) {
        log.info("BulkRetryListener.open>>>开始监听 retryContext.retryCount: {}", retryContext.getRetryCount());
        retryContext.setAttribute(KEY, "我是Retry上下文中存入的数据");
        // 否决整个重试
        // return false;
        // 继续重试
        return true;
    }

    /**
     * 方法在重试结束后调用，用于清理重试过程中持有的资源或状态。参数包括当前的RetryContext、RetryCallback以及最后一次执行回调抛出的异常
     */
    @Override
    public <T, E extends Throwable> void close(RetryContext retryContext, RetryCallback<T, E> retryCallback, Throwable throwable) {
        log.info("key:{}", retryContext.getAttribute(KEY));
        log.info("BulkRetryListener.close>>>关闭");
    }

    /**
     * 方法在每次重试失败后调用，用于处理失败的情况。参数包括当前的RetryContext、RetryCallback以及最后一次执行回调抛出的异常
     */
    @Override
    public <T, E extends Throwable> void onError(RetryContext retryContext, RetryCallback<T, E> retryCallback, Throwable throwable) {
        log.info("BulkRetryListener.onError>>>报错了");
    }
}
